package cz.stv.pecinovsky.město;

import cz.stv.pecinovsky.správceplátna.IMultiposuvný;
import cz.stv.pecinovsky.správceplátna.Kreslítko;
import cz.stv.pecinovsky.správceplátna.Multipřesouvač;
import cz.stv.pecinovsky.správceplátna.SprávcePlátna;

import cz.stv.pecinovsky.utility.Pozice;
import cz.stv.pecinovsky.utility.Směr8;


/*******************************************************************************
 * Instance třídy {@code Otočný} představují dekorátory posuvných objektů,
 * které je dekorují schopností jezdit po okruhu.
 *
 * @author  Rudolf PECINOVSKÝ
 * @version 1.10.2678 — 2011-10-27
 */
public class Otočný implements IMultiposuvný, IOtočný
     {
//== KONSTANTNÍ ATRIBUTY TŘÍDY =================================================

    /** Implicitní rychlost, kterou se objekty přesouvají. */
    private static final int IMPLICITNÍ_RYCHLOST = 100;

    /** Správce plátna, na němž budou objekty zobrazovány. */
    private static final SprávcePlátna SP = SprávcePlátna.getInstance();



//== PROMĚNNÉ ATRIBUTY TŘÍDY ===================================================
//== STATICKÝ INICIALIZAČNÍ BLOK - STATICKÝ KONSTRUKTOR ========================
//== KONSTANTNÍ ATRIBUTY INSTANCÍ ==============================================

    /** Dekorovaný objekt, kterým se bude objíždět nějaký okruh. */
    private final IOtočný dekorovaný;



//== PROMĚNNÉ ATRIBUTY INSTANCÍ ================================================

    /** Rychlost, kterou se objekt přesouvá. */
    private int rychlost = IMPLICITNÍ_RYCHLOST;

    /** Pole, ze kterého objekt naposledy "vyjel". */
    private PoleCesty pole;



//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ TŘÍDY ========================================
//== OSTATNÍ NESOUKROMÉ METODY TŘÍDY ===========================================

//##############################################################################
//== KONSTRUKTORY A TOVÁRNÍ METODY =============================================

    /***************************************************************************
     * Vytvoří novou instanci obalující a dekorující zadaný posuvný objekt.
     *
     * @param dekorovaný Obalovaný a dekorovaný objekt
     */
    public Otočný(IOtočný dekorovaný)
    {
        this.dekorovaný = dekorovaný;
    }



//== ABSTRAKTNÍ METODY =========================================================
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ INSTANCÍ =====================================

    /***************************************************************************
     * Vrátí základní délku, od níž se odvozují všechny rozměry objektu.
     *
     * @return Velikost modulu
     */
    @Override
    public int getModul()
    {
        return dekorovaný.getModul();
    }


    /***************************************************************************
     * Nastaví nový základní rozměr objektu,
     * od nějž se odvozují jeho ostatní rozměry.
     *
     * @param modul Nově nastavovaný modul
     */
    @Override
    public void setModul(int modul)
    {
        dekorovaný.setModul(modul);
    }


    /***************************************************************************
     * Vrátí přepravku se souřadnicemi instance.
     *
     * @return  Přepravka se souřadnicemi instance
     */
    @Override
    public Pozice getPozice()
    {
        return dekorovaný.getPozice();
    }


    /***************************************************************************
     * Nastaví novou pozici instance.
     *
     * @param pozice  Nová pozice instance
     */
    @Override
    public void setPozice(Pozice pozice)
    {
        dekorovaný.setPozice(pozice);
    }


    /***************************************************************************
     * Nastaví novou pozici instance.
     *
     * @param x   Nová x-ová pozice instance
     * @param y   Nová y-ová pozice instance
     */
    @Override
    public void setPozice(int x, int y)
    {
        dekorovaný.setPozice(x, y);
    }


    /***************************************************************************
     * Nastaví novou rychlost přesunu instance;
     * tato rychlost ale začne platit až od příštího startu.
     *
     * @param rychlost  Nastavovaná rychlost
     */
    public void setRychlost(int rychlost)
    {
        this.rychlost = rychlost;
    }


    /***************************************************************************
     * Vrátí směr, do nějž je instance natočena.
     *
     * @return Směr, do nějž je instance natočena
     */
    @Override
    public Směr8 getSměr()
    {
        return dekorovaný.getSměr();
    }


    /***************************************************************************
     * Natočí instanci do nového směru.
     *
     * @param směr Směr, do nějž chceme instanci natočit
     */
    @Override
    public void setSměr(Směr8 směr)
    {
        dekorovaný.setSměr(směr);
    }



//== OSTATNÍ NESOUKROMÉ METODY INSTANCÍ ========================================

    /***************************************************************************
     * Prostřednictvím dodaného kreslítka vykreslí obraz své instance.
     *
     * @param kreslítko Kreslítko, které nakreslí instanci
     */
    @Override
    public void nakresli(Kreslítko kreslítko)
    {
        dekorovaný.nakresli(kreslítko);
    }


    /***************************************************************************
     * Přistaví dekorovaný objekt na zadaný okruh
     * a začne s ním tento okruh objíždět.
     *
     * @param okruh Okruh, který se má objíždět
     */
    public void objížděj(Okruh okruh)
    {
        PoleCesty start = okruh.getPočátek();
        pokračujZ(start);
    }


    /***************************************************************************
     * Přistaví dekorovaný objekt na zadané pole a vyjede s ním dál.
     *
     * @param pole Výchozí pole, ze kterého se bude pokračovat dál
     */
    public void pokračujZ(PoleCesty pole)
    {
        this.pole = pole;
        Pozice pozice = pole.getPozice();
        dekorovaný.setPozice(pozice);
        dekorovaný.setModul(pole.getModul());
        SP.přidej(this);
        přesunuto();
    }


    /***************************************************************************
     * Metoda vyvolaná multipřesouvačem poté, co dovedl svěřený objekt
     * do zadané cílové pozice. Při svém typickém použití metoda nastaví
     * novou cílovou pozici své instance a instanci opět předá multipřesouvači.
     */
    @Override
    public void přesunuto()
    {
        Směr8 směr = pole.getSměr();
        dekorovaný.setSměr(směr);
        pole = pole.getDalší();
        Pozice pozice = pole.getPozice();
        Multipřesouvač m = Multipřesouvač.getInstance();
        m.přesuňRychlostí(rychlost, this, pozice);
    }


    /***************************************************************************
     * Vrací textovou reprezentaci (podpis) dané instance
     * používanou především k ladicím účelům.
     *
     * @return Požadovaná textová reprezentace
     */
    @Override
    public String toString()
    {
        return "Pojízdný_(" + dekorovaný.toString() + ")";
    }



//== SOUKROMÉ A POMOCNÉ METODY TŘÍDY ===========================================
//== SOUKROMÉ A POMOCNÉ METODY INSTANCÍ ========================================
//== INTERNÍ DATOVÉ TYPY =======================================================
//== TESTY A METODA MAIN =======================================================
//
//    /***************************************************************************
//     * Testovací metoda.
//     */
//    public static void test()
//    {
//        Otočný inst = new Otočný();
//    }
//    /** @param args Parametry příkazového řádku - nepoužívané. */
//    public static void main( String[] args )  {  test();  }
}

